home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2004 July
/
CMCD0704.ISO
/
Software
/
Freeware
/
Comunicatii
/
htttrack
/
httrack-3.32-2.exe
/
{app}
/
src_win
/
WinHTTrack
/
DirTreeView.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2004-01-24
|
21KB
|
750 lines
// DirTreeView.cpp : implementation file
//
#include "stdafx.h"
#include "winhttrack.h"
#include "DirTreeView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
extern "C" {
#include "HTTrackInterface.h"
#include "htsbase.h"
};
#include "MainFrm.h"
CDirTreeView* this_DirTreeView=NULL;
/////////////////////////////////////////////////////////////////////////////
// CDirTreeView
IMPLEMENT_DYNCREATE(CDirTreeView, CTreeView)
CDirTreeView::CDirTreeView()
{
this_DirTreeView=this;
redraw_in_progress=0;
timer=0;
count_whandle=0;
docType="<nullType>";
}
CDirTreeView::~CDirTreeView()
{
WaitThreads();
this_DirTreeView=NULL;
if (imagelist.m_hImageList) {
imagelist.Detach();
imagelist.m_hImageList=NULL;
}
}
BEGIN_MESSAGE_MAP(CDirTreeView, CTreeView)
//{{AFX_MSG_MAP(CDirTreeView)
ON_WM_TIMER()
ON_WM_SHOWWINDOW()
ON_NOTIFY_REFLECT(TVN_ITEMEXPANDING, OnItemexpanding)
ON_NOTIFY_REFLECT(NM_DBLCLK, OnDblclk)
ON_NOTIFY_REFLECT(NM_RCLICK, OnRclick)
ON_NOTIFY_REFLECT(TVN_ENDLABELEDIT, OnEndlabeledit)
ON_NOTIFY_REFLECT(TVN_KEYDOWN, OnKeydown)
ON_NOTIFY_REFLECT(NM_CLICK, OnClick)
ON_WM_KILLFOCUS()
ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelchanged)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDirTreeView drawing
void CDirTreeView::OnDraw(CDC* pDC)
{
CDocument* pDoc = GetDocument();
// TODO: add draw code here
}
/////////////////////////////////////////////////////////////////////////////
// CDirTreeView diagnostics
#ifdef _DEBUG
void CDirTreeView::AssertValid() const
{
CTreeView::AssertValid();
}
void CDirTreeView::Dump(CDumpContext& dc) const
{
CTreeView::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CDirTreeView message handlers
BOOL CDirTreeView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
{
dwStyle|=(TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS|TVS_SHOWSELALWAYS|TVS_EDITLABELS);
//dwStyle|=(TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS|TVS_SHOWSELALWAYS|TVS_DISABLEDRAGDROP);
//
dwStyle&=(~(TVS_NOTOOLTIPS)); /* disabled */
/*
dwStyle|=(WS_DISABLED);
dwStyle&=(~(WS_VISIBLE));
*/
int r=CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
GetTreeCtrl().SetImageList(&imagelist,TVSIL_NORMAL);
/*GetTreeCtrl().SetToolTips(&m_TreeViewToolTip);*/
RefreshTree();
return r;
}
void CDirTreeView::RefreshTree() {
CTreeCtrl& tree=GetTreeCtrl();
if (!tree) return; /* error */
tree.DeleteAllItems();
int len=32768;
char* adr=(char*)malloc(len+4);
if (adr) {
if (GetLogicalDriveStrings(len,adr)>0) {
char*a=adr;
while(*a) {
char* next=a+strlen(a)+1;
if (*(a+strlen(a)-1)=='\\')
*(a+strlen(a)-1)='\0';
HTREEITEM it=tree.InsertItem(a);
if (it) {
tree.SetItemText(it,"");
tree.InsertItem("expanding..",it,TVI_SORT);
// icone
char name[256];
strcpybuff(name,a);
strcatbuff(name,"\\");
SHFILEINFO info;
if (SHGetFileInfo(name,0,&info,sizeof(info),SHGFI_SMALLICON | SHGFI_SYSICONINDEX | SHGFI_SHELLICONSIZE | SHGFI_DISPLAYNAME)) {
//SHGetFileInfo(name,0,&info,sizeof(info),SHGFI_SMALLICON | SHGFI_SYSICONINDEX | SHGFI_TYPENAME | SHGFI_SHELLICONSIZE | SHGFI_DISPLAYNAME | SHGFI_ATTRIBUTES);
tree.SetItemImage(it,info.iIcon,info.iIcon);
CString disp=info.szDisplayName;
if (disp.ReverseFind('('))
disp=disp.Left(disp.Find('('));
disp+="<"; disp+=a; disp+=">";
tree.SetItemText(it,disp);
}
}
a=next;
}
}
free(adr);
}
BuildTrackHandles();
}
/* remise α zΘro */
void CDirTreeView::ResetTree() {
if (!GetTreeCtrl()) return; /* error */
RefreshTree();
StartTimer();
}
/* attendre fin des threads refresh */
void CDirTreeView::WaitThreads() {
/* attendre */
int w=0;
while((redraw_in_progress) && (w<10)) {
Sleep(100);
w++;
}
}
void CDirTreeView::OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult)
{
*pResult = 0;
if (GetTreeCtrl().GetStyle() & WS_VISIBLE) { /* sinon pas de refresh */
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
// find out what item is getting expanded, and send that to Expand(hItem, TVE_EXPAND)
if (pNMTreeView->hdr.code == TVN_ITEMEXPANDING)
{
HTREEITEM hIT = pNMTreeView->itemNew.hItem;
DestroyTrackHandles();
if (!RefreshDir(hIT))
*pResult = 1;
BuildTrackHandles();
}
}
}
void CDirTreeView::OnSelchanged(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
// find out what item is getting expanded, and send that to Expand(hItem, TVE_EXPAND)
if (pNMTreeView->hdr.code == TVN_SELCHANGED)
{
HTREEITEM hIT = pNMTreeView->itemNew.hItem;
CString st=GetItemPath(hIT);
CWnd* top_window=this;
while(top_window->GetParent())
top_window=top_window->GetParent();
SetWindowTextCP(((CMainFrame*)top_window)->m_wndStatusBar, st);
}
*pResult = 0;
}
void CDirTreeView::OnDblclk(NMHDR* pNMHDR, LRESULT* pResult)
{
HTREEITEM selected=GetTreeCtrl().GetSelectedItem();
if (selected) {
if (!GetTreeCtrl().ItemHasChildren(selected)) {
CString name=GetItemPath(selected);
if (name.Right(1)=="\\")
name=name.Left(name.GetLength()-1);
DWORD attrb=GetFileAttributes(name);
if (attrb!=0xFFFFFFFF) {
if ( !(attrb & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_TEMPORARY)) ) {
CWaitCursor wait;
if (docType.CompareNoCase(name.Right(docType.GetLength()))==0) {
CWinApp* app=AfxGetApp();
POSITION pos;
pos=app->GetFirstDocTemplatePosition();
CDocTemplate* templ = app->GetNextDocTemplate(pos);
pos=templ->GetFirstDocPosition();
CDocument* doc = templ->GetNextDoc(pos);
if (doc) {
//if (doc->SaveModified()) {
AfxGetApp()->OpenDocumentFile(name);
//}
}
} else {
/* Lancer ShellEx en arriΦre plan */
AfxBeginThread(CDirTreeViewShellEx,new CString(name));
}
}
}
}
}
*pResult = 0;
}
void CDirTreeView::OnClick(NMHDR* pNMHDR, LRESULT* pResult)
{
CTreeCtrl& tree=GetTreeCtrl();
if (!tree) return;
HTREEITEM curr_selected=tree.GetDropHilightItem();
if (!curr_selected)
curr_selected=tree.GetSelectedItem();
if (curr_selected) {
/*
CString st=GetItemPath(curr_selected);
CWnd* top_window=this;
while(top_window->GetParent())
top_window=top_window->GetParent();
((CMainFrame*)top_window)->m_wndStatusBar.SetWindowTextCP(this, st);
*/
}
*pResult = 0;
}
void CDirTreeView::OnRclick(NMHDR* pNMHDR, LRESULT* pResult)
{
CTreeCtrl& tree=GetTreeCtrl();
if (!tree) return;
HTREEITEM curr_selected=tree.GetDropHilightItem();
if (!curr_selected)
curr_selected=tree.GetSelectedItem();
if (curr_selected) {
CString st=GetItemPath(curr_selected);
AfxMessageBox(st);
}
*pResult = 0;
}
CString CDirTreeView::GetItemName(HTREEITEM position) {
CString st=GetTreeCtrl().GetItemText(position);
if (st.Find('<')) {
if (st.Right(2)==":>") {
st=st.Mid(st.Find('<')+1);
st=st.Left(st.GetLength()-1);
}
}
return st;
}
CString CDirTreeView::GetItemPath(HTREEITEM position) {
if (position) {
HTREEITEM parent_it=GetTreeCtrl().GetParentItem(position);
CString st=GetItemName(position);
CString slash="";
if (GetTreeCtrl().ItemHasChildren(position))
slash="\\";
if (st.GetLength())
return GetItemPath(parent_it)+st+slash;
else
return GetItemPath(parent_it);
} else
return "";
}
HTREEITEM CDirTreeView::GetPathItem(CString path,BOOL open,BOOL nofail,BOOL nohide,HTREEITEM rootposition) {
CTreeCtrl& tree=GetTreeCtrl();
if (!tree) return NULL; /* error */
//
HTREEITEM return_value=NULL;
//
CString left="",right="";
int pos=path.Find('\\');
if (pos<0)
left=path;
else {
left=path.Left(pos);
right=path.Mid(pos+1);
}
if (!nohide)
tree.ModifyStyle(WS_VISIBLE,0);
HTREEITEM position;
if (!rootposition) {
rootposition=tree.GetRootItem();
/* position initiale */
position=rootposition;
} else {
// Ouvrir?
if (open) {
if (tree.ItemHasChildren(rootposition)) { /* si enfants */
if (!(tree.GetItemState(rootposition,TVIF_STATE) & TVIS_EXPANDED)) { /* si non ouvert */
/*tree.SetItemState(rootposition,TVIF_STATE,
tree.GetItemState(rootposition,TVIF_STATE) | TVIS_EXPANDED);
*/
tree.Expand(rootposition,TVE_EXPAND);
RefreshDir(rootposition,TRUE);
}
}
}
/* position initiale */
position=tree.GetChildItem(rootposition);
}
left.MakeLower();
while(position) {
CString st=GetItemName(position);
st.MakeLower();
if (st==left) {
if (right.GetLength())
position=GetPathItem(right,open,nofail,TRUE,position);
else
return_value=position; // trouvΘ
position=NULL;
}
if (position)
position=tree.GetNextSiblingItem(position);
}
// liste visible
if (!nohide) {
tree.ModifyStyle(0,WS_VISIBLE);
//RedrawWindow();
tree.GetParent()->RedrawWindow();
}
if (return_value)
return return_value;
else if (nofail)
return rootposition;
else
return NULL;
}
BOOL CDirTreeView::EnsureVisible(CString path) {
if (!GetTreeCtrl()) return FALSE; /* error */
#if 0
/* Lancer refresh en arriΦre plan */
refreshPath=path;
StopTimer();
AfxBeginThread(CDirTreeViewRefresh,this);
return TRUE;
#else
CWaitCursor wait;
HTREEITEM pos=GetPathItem(path,TRUE,TRUE);
if (pos) {
GetTreeCtrl().EnsureVisible(pos);
} else
return FALSE;
return TRUE;
#endif
}
BOOL CDirTreeView::EnsureVisibleBl(CString path) {
if (!GetTreeCtrl()) return FALSE; /* error */
CWaitCursor wait;
int return_value=TRUE;
StopTimer();
HTREEITEM pos=GetPathItem(path,TRUE,TRUE);
if (pos) {
GetTreeCtrl().EnsureVisible(pos);
} else
return_value=FALSE;
StartTimer();
return return_value;
}
void CDirTreeView::RefreshPos(HTREEITEM position) {
RefreshDir(position);
}
BOOL CDirTreeView::RefreshDir(HTREEITEM position,BOOL nohide) {
CTreeCtrl& tree=GetTreeCtrl();
if (!tree) return FALSE; /* error */
CWaitCursor wait;
CString path=GetItemPath(position);
CString backup_visibles="\n";
// Pour FindFirstFile/FindNextFile
WIN32_FIND_DATA find;
int type;
HANDLE h = FindFirstFile(path+"*.*",&find);
// accessible
if (h!=INVALID_HANDLE_VALUE) {
// liste invisible
if (!nohide)
tree.ModifyStyle(WS_VISIBLE,0);
{ // backuper ΘlΘments visibles
HTREEITEM it=tree.GetChildItem(position);
int backup_visibles_count=0;
while(it) {
if (tree.ItemHasChildren(it)) { /* si enfants */
if (tree.GetItemState(it,TVIF_STATE) & TVIS_EXPANDED) { /* si ouvert */
backup_visibles+=(GetItemPath(it)+"\n");
backup_visibles_count++;
}
}
it=tree.GetNextVisibleItem(it);
}
if (!backup_visibles_count)
backup_visibles="";
}
{ // effacer la liste
HTREEITEM it;
while(it=tree.GetChildItem(position))
tree.DeleteItem(it);
}
// chargement de la liste
HTREEITEM last_dir_it=tree.GetRootItem();
for(type=0;type<2;type++) {
if (h != INVALID_HANDLE_VALUE) {
do {
if (!(find.dwFileAttributes & (FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN))) {
if (strcmp(find.cFileName,"..")) {
if (strcmp(find.cFileName,".")) {
HTREEITEM it=NULL;
if (find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
if (type==0) {
if (IsWindow(tree.m_hWnd)) {
it=tree.InsertItem(find.cFileName,position);
tree.InsertItem("expanding..",it,TVI_SORT);
}
}
} else {
if (type==1) {
if (IsWindow(tree.m_hWnd))
it=tree.InsertItem(find.cFileName,position,last_dir_it);
}
}
// changer icone
if (it) {
SHFILEINFO info;
SHGetFileInfo(path+find.cFileName,0,&info,sizeof(info),SHGFI_SYSICONINDEX);
//SHGetFileInfo(path+find.cFileName,0,&info,sizeof(info),SHGFI_SMALLICON | SHGFI_SYSICONINDEX | SHGFI_TYPENAME | SHGFI_SHELLICONSIZE | SHGFI_DISPLAYNAME | SHGFI_ATTRIBUTES);
if (IsWindow(tree.GetSafeHwnd()))
tree.SetItemImage(it,info.iIcon,info.iIcon);
}
}
}
}
} while(FindNextFile(h,&find));
FindClose(h);
}
if (type==0)
h = FindFirstFile(path+"*.*",&find);
}
// restaurer ΘlΘments visibles
RestoreVisibles(position,backup_visibles);
// liste visible
if (!nohide)
tree.ModifyStyle(0,WS_VISIBLE);
}/* **OLD
else
tree.Expand(position,TVE_COLLAPSE);
*/
// Redessiner
if (!nohide)
GetParent()->RedrawWindow();
return (h!=INVALID_HANDLE_VALUE);
}
void CDirTreeView::RestoreVisibles(HTREEITEM position,CString& backup_visibles) {
CTreeCtrl& tree=GetTreeCtrl();
if (!tree) return; /* error */
if (backup_visibles.GetLength()) {
// rΘouvrir les ΘlΘments visibles
HTREEITEM it=tree.GetChildItem(position);
while(it) {
if (backup_visibles.Find("\n"+GetItemPath(it)+"\n")>=0) {
tree.Expand(it,TVE_EXPAND);
RefreshDir(it,TRUE); /* car appelΘ par RefreshDir lui mΩme */
RestoreVisibles(it,backup_visibles);
}
it=tree.GetNextSiblingItem(it);
}
}
}
void CDirTreeView::StartTimer() {
if (!timer) {
//whandle=FindFirstChangeNotification("C:\\",TRUE,FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_DIR_NAME);
BuildTrackHandles();
timer=SetTimer(WM_TIMER,1000,NULL);
}
}
void CDirTreeView::StopTimer() {
if (timer) {
DestroyTrackHandles();
KillTimer(timer);
timer=0;
}
}
void CDirTreeView::DestroyTrackHandles()
{
/* Fermer handles actuels */
if (count_whandle) {
int i;
for(i=0;i<count_whandle;i++)
FindCloseChangeNotification(whandle[i]);
count_whandle=0;
}
}
void CDirTreeView::BuildTrackHandles()
{
if (!GetTreeCtrl()) return; /* error */
DestroyTrackHandles();
/* Lecture ΘlΘments du root visibles (non, c'est pas rΘcursif vu que ce sont les Θlts visibles) */
CTreeCtrl& it=GetTreeCtrl();
HTREEITEM pos=it.GetFirstVisibleItem();
while(pos) {
CString path=GetItemPath(pos);
CFileStatus status;
if (it.ItemHasChildren(pos)) { /* surveiller si enfants */
if (it.GetItemState(pos,TVIF_STATE) & TVIS_EXPANDED) { /* si ouvert */
if (CFile::GetStatus(path.Left(path.GetLength()-1),status)) { // rΘpertoire (note: path sans le / final)
if (status.m_attribute & 0x10 ) { /* directory = 0x10 */
whandle[count_whandle]=FindFirstChangeNotification(path,FALSE,FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_DIR_NAME);
if (whandle[count_whandle] != INVALID_HANDLE_VALUE) {
pos_whandle[count_whandle]=pos;
count_whandle++;
}
}
}
}
}
pos=it.GetNextVisibleItem(pos);
}
}
void CDirTreeView::DoTrackHandles()
{
CTreeCtrl& tree=GetTreeCtrl();
if (!tree) return; /* error */
if (count_whandle) {
int r=(WaitForMultipleObjects(count_whandle,whandle,FALSE,0)-WAIT_OBJECT_0);
if ( (r>=0) && (r<count_whandle) ) { // un item a changΘ
DestroyTrackHandles();
HTREEITEM pos=pos_whandle[r];
RefreshPos(pos);
tree.SetItemState(pos,TVIS_BOLD,TVIS_BOLD);
BuildTrackHandles(); /* probleme: on va en rater certains.. */
//FindNextChangeNotification(whandle[r]);
}
/*
int i;
for(i=0;i<count_whandle;i++)
FindNextChangeNotification(whandle[i]);
*/
}
}
void CDirTreeView::OnTimer(UINT nIDEvent)
{
DoTrackHandles();
CTreeView::OnTimer(nIDEvent);
}
void CDirTreeView::OnShowWindow(BOOL bShow, UINT nStatus)
{
static BOOL detach_flag=FALSE;
if (detach_flag == bShow) return;
detach_flag=bShow;
if (bShow) {
HIMAGELIST hSystemImageList;
SHFILEINFO SHFileInfo;
hSystemImageList = (HIMAGELIST)SHGetFileInfo("", 0, &SHFileInfo, sizeof(SHFILEINFO), SHGFI_SYSICONINDEX|SHGFI_SMALLICON);
if (!hSystemImageList) {
MessageBox("Error: SHGetFileInfo");
//return;
} else {
imagelist.Attach(hSystemImageList);
}
} else {
if (imagelist.m_hImageList) {
imagelist.Detach();
imagelist.m_hImageList=NULL;
}
}
//
CTreeView::OnShowWindow(bShow, nStatus);
if (bShow)
StartTimer();
else
StopTimer();
}
void CDirTreeView::OnEndlabeledit(NMHDR* pNMHDR, LRESULT* pResult)
{
TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
// TODO: Add your control notification handler code here
if (pTVDispInfo->item.mask & TVIF_TEXT) {
if (pTVDispInfo->item.pszText) {
if (strlen(pTVDispInfo->item.pszText)) {
CString path=GetItemPath(pTVDispInfo->item.hItem);
if (path.Right(1)=="\\")
path=path.Left(path.GetLength()-1);
CString newpath=path.Left(path.ReverseFind('\\')+1)+pTVDispInfo->item.pszText;
if (path != newpath) {
if (!MoveFile(path,newpath)) {
AfxMessageBox("Unable to rename "+path+" to "+newpath+"!");
} else {
GetTreeCtrl().SetItemText(pTVDispInfo->item.hItem,pTVDispInfo->item.pszText);
}
}
}
}
}
*pResult = 0;
}
void CDirTreeView::OnKeydown(NMHDR* pNMHDR, LRESULT* pResult)
{
TV_KEYDOWN* pTVKeyDown = (TV_KEYDOWN*)pNMHDR;
HTREEITEM selected=GetTreeCtrl().GetSelectedItem();
*pResult = 0;
int key=pTVKeyDown->wVKey ;
switch(key) {
case 32:
if (selected) {
GetTreeCtrl().Expand(selected,TVE_TOGGLE);
*pResult = -1;
}
break;
case 13: case 10:
if (selected) {
GetTreeCtrl().Expand(selected,TVE_TOGGLE);
*pResult = -1;
}
break;
/*default:
printf("\a");
break;
*/
}
}
/*
IMPLEMENT_DYNAMIC(CDirTreeViewShellEx, CWinThread)
/////////////////////////////////////////////////////////////////////////////
// CDirTreeViewShellEx
BOOL CDirTreeViewShellEx::InitInstance() {
if (!ShellExecute(NULL,NULL,File,NULL,NULL,SW_SHOWNORMAL)) {
}
return 0;
}
*/
UINT CDirTreeViewShellEx( LPVOID pP ) {
CWaitCursor wait;
CString* File=(CString*) pP;
if (!ShellExecute(NULL,"open",*File,NULL,NULL,SW_SHOWNORMAL)) {
}
delete File;
return 0;
}
UINT CDirTreeViewRefresh( LPVOID pP ) {
CDirTreeView* _this=(CDirTreeView*) pP;
if (!_this->redraw_in_progress) {
_this->redraw_in_progress=1;
_this->EnsureVisibleBl(_this->refreshPath);
_this->redraw_in_progress=0;
}
return 0;
}
void CDirTreeView::OnKillFocus(CWnd* pNewWnd)
{
CTreeView::OnKillFocus(pNewWnd);
CWnd* top_window=this;
while(top_window->GetParent())
top_window=top_window->GetParent();
SetWindowTextCP(((CMainFrame*)top_window)->m_wndStatusBar, "");
}